/**
    ATClab - scriptable Air Traffic Control simulations.
    Copyright (C) 2010 openatclab@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/

#ifndef __SCORE_HDR__
#define __SCORE_HDR__

#include <qobject.h>
#include "audio_player.h"
#include "conflictdeclaration.h"

namespace atc {

	const std::string EVENT_ALREADY_ACTIONED( "ALREADY_ACTIONED" );
	const std::string EVENT_HIT_CONFLICT_ONTIME( "HIT_CONFLICT_ONTIME" );
	const std::string EVENT_HIT_CONFLICT_NOT_ONTIME("HIT_CONFLICT_NOT_ONTIME");
	const std::string EVENT_HIT_AFTER_CONFLICT("HIT_AFTER_CONFLICT");
	const std::string EVENT_TOO_LATE_CONFLICT("TOO_LATE_CONFLICT");
	const std::string EVENT_FALSE_ALARM_CONFLICT( "FALSE_ALARM_CONFLICT" );
	const std::string EVENT_FALSE_ALARM_CONFLICT_NON_TARGET( "FALSE_ALARM_CONFLICT_NON_TARGET" );

	const std::string EVENT_HIT_NON_CONFLICT("HIT_NON_CONFLICT");
	const std::string EVENT_TOO_LATE_NON_CONFLICT("TOO_LATE_NON_CONFLICT");
	const std::string EVENT_FALSE_ALARM_NON_CONFLICT("FALSE_ALARM_NON_CONFLICT");
	const std::string EVENT_FALSE_ALARM_NON_CONFLICT_NON_TARGET("FALSE_ALARM_NON_CONFLICT_NON_TARGET");

	const std::string EVENT_PRIOR_CONFLICT_FOR_CONFLICT_PAIR("PRIOR_CONFLICT_FOR_CONFLICT_PAIR");
	const std::string EVENT_PRIOR_CONFLICT_FOR_NON_CONFLICT_PAIR("PRIOR_CONFLICT_FOR_NON_CONFLICT_PAIR");
	const std::string EVENT_PRIOR_CONFLICT_FOR_NON_TARGET_PAIR("PRIOR_CONFLICT_FOR_NON_TARGET_PAIR");
	const std::string EVENT_PRIOR_NON_CONFLICT_FOR_CONFLICT_PAIR("PRIOR_NON_CONFLICT_FOR_CONFLICT_PAIR");
	const std::string EVENT_PRIOR_NON_CONFLICT_FOR_NON_CONFLICT_PAIR("PRIOR_NON_CONFLICT_FOR_NON_CONFLICT_PAIR");
	const std::string EVENT_PRIOR_NON_CONFLICT_FOR_NON_TARGET_PAIR("PRIOR_NON_CONFLICT_FOR_NON_TARGET_PAIR");

	const std::string EVENT_MISS_CONFLICT("MISS_CONFLICT");
	const std::string EVENT_MISS_NON_CONFLICT("MISS_NON_CONFLICT");
	const std::string EVENT_MISSED_ACCEPTANCE( "MISSED_ACCEPTANCE" );

	struct GoalAchievementFormula
	{
		GoalAchievementFormula()
			:	m_ref1(""),
				m_ref2(""),
				m_comparisonOperator("")
		{
		}

		std::string m_ref1;
		std::string m_ref2;
		std::string m_comparisonOperator;
	};

	enum FalseAlarmType
	{
		NO_FALSE_ALARM,
		FALSE_ALARM_TARGET,
		FALSE_ALARM_NON_TARGET
	};

	class ScoreBuilder;

	class Score : public QObject 
	{
		Q_OBJECT
	public:
		Score(const ScoreBuilder&);
		~Score();

		void set_conflicts( ConflictDeclarationMap * conflicts ) { m_conflicts = conflicts; }
		void zero();
		long GetScore() const { return m_score; }
 
		void SetConflictDeclarationScoreEnabled(bool a_enabled)
		{
			m_conflictDeclarationScoreEnabled = a_enabled;
		}

		void SetConflictDeclarationAudioEnabled(bool a_enabled)
		{
			m_conflictDeclarationAudioEnabled = a_enabled;
		}

		void UpdateGoalScores();
		void CheckMissedNonConflicts(bool a_compareToCurrentTime = true, bool a_playAudio = true);
		void CheckMissedConflicts(bool a_compareToCurrentTime = true, bool a_playAudio = true);

	public slots:
		void DeclareConflict(	const std::string&	a_callsign1, 
								const std::string&	a_callsign2);
		void DeclareNonConflict(const std::string&	a_callsign1, 
								const std::string&	a_callsign2);
		void conflict( const std::string &, const std::string & );
		void missed_acceptance();
		void UpdateTime(long a_seconds);

	private:
		ConflictDeclaration*	conflict_declaration(	const std::string &, 
														const std::string &,
														ConflictDeclaration::ConflictType);
		void					score( int, SoundBite, const std::string &, int);
		void					update_score(long);
		FalseAlarmType			FalseAlarm(	std::string a_ac0, 
											std::string a_ac1,
											ConflictDeclaration::ConflictType a_type) const;
	signals:
		void sig_hit();
		void sig_score(long);
		void sig_score_quiet( long );

	private slots:
		void ProvideFeedback();

	private:
		long					m_initialScore;
		long					m_score;
		ConflictDeclarationMap*	m_conflicts;
		ConflictDeclarationMap* m_falseAlarms;
        long					m_currentTimeSecs;
        AudioPlayer&			m_player;

		const int ALREADY_ACTIONED;
		const int HIT_CONFLICT_ONTIME;
		const int HIT_CONFLICT_NOT_ONTIME;
		const int HIT_AFTER_CONFLICT;
		const int TOO_LATE_CONFLICT;
		const int FALSE_ALARM_CONFLICT;
		const int FALSE_ALARM_CONFLICT_NON_TARGET;

		const int HIT_NON_CONFLICT;
		const int TOO_LATE_NON_CONFLICT;
		const int FALSE_ALARM_NON_CONFLICT;
		const int FALSE_ALARM_NON_CONFLICT_NON_TARGET;

		const int PRIOR_CONFLICT_FOR_CONFLICT_PAIR;
		const int PRIOR_CONFLICT_FOR_NON_CONFLICT_PAIR;
		const int PRIOR_CONFLICT_FOR_NON_TARGET_PAIR;
		const int PRIOR_NON_CONFLICT_FOR_CONFLICT_PAIR;
		const int PRIOR_NON_CONFLICT_FOR_NON_CONFLICT_PAIR;
		const int PRIOR_NON_CONFLICT_FOR_NON_TARGET_PAIR;

		const int MISS_CONFLICT;
		const int MISS_NON_CONFLICT;
		const int MISSED_ACCEPTANCE;

		SoundBite AUDIO_NONE;
		SoundBite AUDIO_ALREADY_ACTIONED;
		SoundBite AUDIO_HIT_CONFLICT_ONTIME;
		SoundBite AUDIO_HIT_CONFLICT_NOT_ONTIME;
		SoundBite AUDIO_HIT_AFTER_CONFLICT;
		SoundBite AUDIO_TOO_LATE_CONFLICT;
		SoundBite AUDIO_FALSE_ALARM_CONFLICT;
		SoundBite AUDIO_FALSE_ALARM_CONFLICT_NON_TARGET;
		
		SoundBite AUDIO_HIT_NON_CONFLICT;
		SoundBite AUDIO_TOO_LATE_NON_CONFLICT;
		SoundBite AUDIO_FALSE_ALARM_NON_CONFLICT;
		SoundBite AUDIO_FALSE_ALARM_NON_CONFLICT_NON_TARGET;

		SoundBite AUDIO_PRIOR_CONFLICT_FOR_CONFLICT_PAIR;
		SoundBite AUDIO_PRIOR_CONFLICT_FOR_NON_CONFLICT_PAIR;
		SoundBite AUDIO_PRIOR_CONFLICT_FOR_NON_TARGET_PAIR;
		SoundBite AUDIO_PRIOR_NON_CONFLICT_FOR_CONFLICT_PAIR;
		SoundBite AUDIO_PRIOR_NON_CONFLICT_FOR_NON_CONFLICT_PAIR;
		SoundBite AUDIO_PRIOR_NON_CONFLICT_FOR_NON_TARGET_PAIR;

		SoundBite AUDIO_MISS_CONFLICT;
		SoundBite AUDIO_MISS_NON_CONFLICT;
		SoundBite AUDIO_MISSED_ACCEPTANCE;

		SoundBite AUDIO_BEEP;

		const int ALREADY_ACTIONED_DELAY;
		const int HIT_CONFLICT_ONTIME_DELAY;
		const int HIT_CONFLICT_NOT_ONTIME_DELAY;
		const int HIT_AFTER_CONFLICT_DELAY;
		const int TOO_LATE_CONFLICT_DELAY;
		const int FALSE_ALARM_CONFLICT_DELAY;
		const int FALSE_ALARM_CONFLICT_NON_TARGET_DELAY;

		const int HIT_NON_CONFLICT_DELAY;
		const int TOO_LATE_NON_CONFLICT_DELAY;
		const int FALSE_ALARM_NON_CONFLICT_DELAY;
		const int FALSE_ALARM_NON_CONFLICT_NON_TARGET_DELAY;

		const int PRIOR_CONFLICT_FOR_CONFLICT_PAIR_DELAY;
		const int PRIOR_CONFLICT_FOR_NON_CONFLICT_PAIR_DELAY;
		const int PRIOR_CONFLICT_FOR_NON_TARGET_PAIR_DELAY;
		const int PRIOR_NON_CONFLICT_FOR_CONFLICT_PAIR_DELAY;
		const int PRIOR_NON_CONFLICT_FOR_NON_CONFLICT_PAIR_DELAY;
		const int PRIOR_NON_CONFLICT_FOR_NON_TARGET_PAIR_DELAY;

		const int MISS_CONFLICT_DELAY;
		const int MISS_NON_CONFLICT_DELAY;
		const int MISSED_ACCEPTANCE_DELAY;


	private:
		int									m_delayedScore;
		SoundBite							m_delayedSoundbite;
		bool								m_conflictDeclarationScoreEnabled;
		bool								m_conflictDeclarationAudioEnabled;
		int									m_goalSuccessScoreMultiplier;
		int									m_goalFailureScore;
		GoalAchievementFormula				m_goalSuccessFormula;
		GoalAchievementFormula				m_goalFailFormula;
		std::map<std::string, std::string>	m_eventReferenceMap;
		std::map<std::string, std::string>	m_correctDecisionLinks;
		std::map<std::string, std::string>	m_incorrectDecisionLinks;
	};


	class ScoreBuilder 
	{
		friend class Score;

	public:
		ScoreBuilder();
		~ScoreBuilder();

		// Set scores
		ScoreBuilder* set_score( int x )					
		{ 
			score = x; 

			return this; 
		}
		
		ScoreBuilder*
		SetAlreadyActionedScore(int a_score)
		{
			m_alreadyActionedScore = a_score;

			return this;
		}

		ScoreBuilder* 
		SetHitConflictOnTimeScore(int a_score)
		{ 
			m_hitConflictOnTimeScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetHitConflictNotOnTimeScore(int a_score)			
		{ 
			m_hitConflictNotOnTimeScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetHitAfterConflictScore(int a_score)		
		{ 
			m_hitAfterConflictScore = a_score; 

			return this; 
		}

		ScoreBuilder*
		SetTooLateConflictScore(int a_score)
		{
			m_tooLateConflictScore = a_score;

			return this;
		}

		ScoreBuilder* 
		SetFalseAlarmConflictScore(int a_score)	
		{ 
			m_falseAlarmConflictScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetFalseAlarmConflictNonTargetScore(int a_score)
		{ 
			m_falseAlarmConflictNonTargetScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetHitNonConflictScore(int a_score)
		{ 
			m_hitNonConflictScore = a_score; 

			return this; 
		}

		ScoreBuilder*
		SetTooLateNonConflictScore(int a_score)
		{
			m_tooLateNonConflictScore = a_score;

			return this;
		}

		ScoreBuilder* 
		SetFalseAlarmNonConflictScore(int a_score)
		{ 
			m_falseAlarmNonConflictScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetFalseAlarmNonConflictNonTargetScore(int a_score)
		{ 
			m_falseAlarmNonConflictNonTargetScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetMissConflictScore(int a_score)				
		{ 
			m_missConflictScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetMissNonConflictScore(int a_score)				
		{ 
			m_missNonConflictScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetPriorConflictForConflictPairScore(int a_score)	
		{ 
			m_priorConflictForConflictPairScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetPriorConflictForNonConflictPairScore(int a_score)	
		{ 
			m_priorConflictForNonConflictPairScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetPriorConflictForNonTargetPairScore(int a_score)	
		{ 
			m_priorConflictForNonTargetPairScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetPriorNonConflictForConflictPairScore(int a_score)	
		{ 
			m_priorNonConflictForConflictPairScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetPriorNonConflictForNonConflictPairScore(int a_score)	
		{ 
			m_priorNonConflictForNonConflictPairScore = a_score; 

			return this; 
		}

		ScoreBuilder* 
		SetPriorNonConflictForNonTargetPairScore(int a_score)	
		{ 
			m_priorNonConflictForNonTargetPairScore = a_score; 

			return this; 
		}
		
		ScoreBuilder* set_missed_acceptance_score( int x )	{ missed_acceptance_score = x; return this; }
		
		// Set audio
		ScoreBuilder*
		SetAlreadyActionedAudio(const std::string& a_audio, int a_duration)
		{
			m_alreadyActionedAudio = a_audio;
			m_alreadyActionedAudioDuration = a_duration;

			return this;
		}

		ScoreBuilder* 
		SetHitConflictOnTimeAudio(const std::string &a, int d ) 
		{ 
			m_hitConflictOnTimeAudio = a;                
			m_hitConflictOnTimeAudioDuration = d;                
			return this; 
		}

		ScoreBuilder* 
		SetHitConflictNotOnTimeAudio(const std::string &a, int d ) 
		{ 
			m_hitConflictNotOnTimeAudio = a;                
			m_hitConflictNotOnTimeAudioDuration = d;                
			return this; 
		}

		ScoreBuilder*     
		SetHitAfterConflictAudio(const std::string &a, int d) 
		{ 
			m_hitAfterConflictAudio = a;     
			m_hitAfterConflictAudioDuration = d;     
			return this; 
		}

		ScoreBuilder*
		SetTooLateConflictAudio(const std::string& a, int d)
		{
			m_tooLateConflictAudio = a;
			m_tooLateConflictAudioDuration = d;

			return this;
		}

		ScoreBuilder* 
		SetFalseAlarmConflictAudio(const std::string &a, int d ) 
		{ 
			m_falseAlarmConflictAudio = a;        
			m_falseAlarmConflictAudioDuration = d;        

			return this; 
		}

		ScoreBuilder* 
		SetFalseAlarmConflictNonTargetAudio(const std::string &a, int d ) 
		{ 
			m_falseAlarmConflictNonTargetAudio = a;        
			m_falseAlarmConflictNonTargetAudioDuration = d;        

			return this; 
		}

		ScoreBuilder* 
		SetHitNonConflictAudio(const std::string &a, int d ) 
		{ 
			m_hitNonConflictAudio = a; 
			m_hitNonConflictAudioDuration = d; 

			return this; 
		}

		ScoreBuilder*
		SetTooLateNonConflictAudio(const std::string& a, int d)
		{
			m_tooLateNonConflictAudio = a;
			m_tooLateNonConflictAudioDuration = d;

			return this;
		}

		ScoreBuilder* 
		SetFalseAlarmNonConflictAudio(const std::string &a, int d ) 
		{ 
			m_falseAlarmNonConflictAudio = a;        
			m_falseAlarmNonConflictAudioDuration = d;        

			return this; 
		}

		ScoreBuilder* 
		SetFalseAlarmNonConflictNonTargetAudio(const std::string &a, int d ) 
		{ 
			m_falseAlarmNonConflictNonTargetAudio = a;        
			m_falseAlarmNonConflictNonTargetAudioDuration = d;        

			return this; 
		}
		
		ScoreBuilder* 
		SetMissConflictAudio(const std::string &a, int d) 
		{ 
			m_missConflictAudio = a;               
			m_missConflictAudioDuration = d;               

			return this; 
		}

		ScoreBuilder* 
		SetMissNonConflictAudio(const std::string &a, int d) 
		{ 
			m_missNonConflictAudio = a;               
			m_missNonConflictAudioDuration = d;               

			return this; 
		}

		ScoreBuilder* 
		SetPriorConflictForConflictPairAudio(const std::string &a, int d) 
		{ 
			m_priorConflictForConflictPairAudio = a; 
			m_priorConflictForConflictPairAudioDuration = d; 

			return this; 
		}
		
		ScoreBuilder* 
		SetPriorConflictForNonConflictPairAudio(const std::string &a, int d) 
		{ 
			m_priorConflictForNonConflictPairAudio = a; 
			m_priorConflictForNonConflictPairAudioDuration = d; 

			return this; 
		}

		ScoreBuilder* 
		SetPriorConflictForNonTargetPairAudio(const std::string &a, int d) 
		{ 
			m_priorConflictForNonTargetPairAudio = a; 
			m_priorConflictForNonTargetPairAudioDuration = d; 

			return this; 
		}

		ScoreBuilder* 
		SetPriorNonConflictForConflictPairAudio(const std::string &a, int d) 
		{ 
			m_priorNonConflictForConflictPairAudio = a; 
			m_priorNonConflictForConflictPairAudioDuration = d; 
			
			return this; 
		}

		ScoreBuilder* 
		SetPriorNonConflictForNonConflictPairAudio(const std::string &a, int d) 
		{ 
			m_priorNonConflictForNonConflictPairAudio = a; 
			m_priorNonConflictForNonConflictPairAudioDuration = d; 
			
			return this; 
		}

		ScoreBuilder* 
		SetPriorNonConflictForNonTargetPairAudio(const std::string &a, int d) 
		{ 
			m_priorNonConflictForNonTargetPairAudio = a; 
			m_priorNonConflictForNonTargetPairAudioDuration = d; 
			
			return this; 
		}
				
		ScoreBuilder*  set_missed_acceptance_audio( const std::string &a, int d ) { missed_acceptance_audio = a;  missed_acceptance_audio_duration = d;  return this; }

		// Set scoring delays
		ScoreBuilder*
		SetAlreadyActionedDelay(int a_delaySecs)
		{
			m_alreadyActionedDelay = a_delaySecs;

			return this;
		}

		ScoreBuilder*
		SetHitConflictOnTimeDelay(int a_delaySecs)
		{
			m_hitConflictOnTimeDelay = a_delaySecs;

			return this;
		}

        ScoreBuilder* 
		SetHitConflictNotOnTimeDelay(int a_delaySecs)
		{
			m_hitConflictNotOnTimeDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetHitAfterConflictDelay(int a_delaySecs)
		{
			m_hitAfterConflictDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetTooLateConflictDelay(int a_delaySecs)
		{
			m_tooLateConflictDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetFalseAlarmConflictDelay(int a_delaySecs)
		{
			m_falseAlarmConflictDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetFalseAlarmConflictNonTargetDelay(int a_delaySecs)
		{
			m_falseAlarmConflictNonTargetDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetHitNonConflictDelay(int a_delaySecs)
		{
			m_hitNonConflictDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetTooLateNonConflictDelay(int a_delaySecs)
		{
			m_tooLateNonConflictDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetFalseAlarmNonConflictDelay(int a_delaySecs)
		{
			m_falseAlarmNonConflictDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetFalseAlarmNonConflictNonTargetDelay(int a_delaySecs)
		{
			m_falseAlarmNonConflictNonTargetDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetPriorConflictForConflictPairDelay(int a_delaySecs)
		{
			m_priorConflictForConflictPairDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetPriorConflictForNonConflictPairDelay(int a_delaySecs)
		{
			m_priorConflictForNonConflictPairDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetPriorConflictForNonTargetPairDelay(int a_delaySecs)
		{
			m_priorConflictForNonTargetPairDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetPriorNonConflictForConflictPairDelay(int a_delaySecs)
		{
			m_priorNonConflictForConflictPairDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetPriorNonConflictForNonConflictPairDelay(int a_delaySecs)
		{
			m_priorNonConflictForNonConflictPairDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetPriorNonConflictForNonTargetPairDelay(int a_delaySecs)
		{
			m_priorNonConflictForNonTargetPairDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetMissConflictDelay(int a_delaySecs)
		{
			m_missConflictDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetMissNonConflictDelay(int a_delaySecs)
		{
			m_missNonConflictDelay = a_delaySecs;
			
			return this;
		}

        ScoreBuilder*
		SetMissedAcceptanceDelay(int a_delaySecs)
		{
			m_missedAcceptanceDelay = a_delaySecs;
			
			return this;
		}

		ScoreBuilder*
		SetReference(const std::string& a_event, const std::string& a_reference)
		{
			std::string event;
			
			if (a_event == "already_actioned" )
			{
				event = EVENT_ALREADY_ACTIONED;
			}
			else if (a_event == "hit_conflict_ontime")
			{
				event = EVENT_HIT_CONFLICT_ONTIME;
			}
			else if (a_event == "hit_conflict_not_ontime") 
			{
				event = EVENT_HIT_CONFLICT_NOT_ONTIME;
			}
			else if (a_event == "hit_after_conflict") 
			{
				event = EVENT_HIT_AFTER_CONFLICT;
			}
			else if (a_event == "too_late_conflict") 
			{
				event = EVENT_TOO_LATE_CONFLICT;
			}
			else if (a_event == "false_alarm_conflict") 
			{
				event = EVENT_FALSE_ALARM_CONFLICT;
			}
			else if (a_event == "false_alarm_conflict_non_target") 
			{
				event = EVENT_FALSE_ALARM_CONFLICT_NON_TARGET;
			}
			else if (a_event == "hit_non_conflict") 
			{
				event = EVENT_HIT_NON_CONFLICT;
			}
			else if (a_event == "too_late_non_conflict") 
			{
				event = EVENT_TOO_LATE_NON_CONFLICT;
			}
			else if (a_event == "false_alarm_non_conflict") 
			{
				event = EVENT_FALSE_ALARM_NON_CONFLICT;
			}
			else if (a_event == "false_alarm_non_conflict_non_target") 
			{
				event = EVENT_FALSE_ALARM_NON_CONFLICT_NON_TARGET;
			}
			else if (a_event == "prior_conflict_for_conflict_pair") 
			{
				event = EVENT_PRIOR_CONFLICT_FOR_CONFLICT_PAIR;
			}
			else if (a_event == "prior_conflict_for_non_conflict_pair") 
			{
				event = EVENT_PRIOR_CONFLICT_FOR_NON_CONFLICT_PAIR;
			}
			else if (a_event == "prior_conflict_for_non_target_pair") 
			{
				event = EVENT_PRIOR_CONFLICT_FOR_NON_TARGET_PAIR;
			}
			else if (a_event == "prior_non_conflict_for_conflict_pair") 
			{
				event = EVENT_PRIOR_NON_CONFLICT_FOR_CONFLICT_PAIR;
			}
			else if (a_event == "prior_non_conflict_for_non_conflict_pair") 
			{
				event = EVENT_PRIOR_NON_CONFLICT_FOR_NON_CONFLICT_PAIR;
			}
			else if (a_event == "prior_non_conflict_for_non_target_pair") 
			{
				event = EVENT_PRIOR_NON_CONFLICT_FOR_NON_TARGET_PAIR;
			}
			else if (a_event == "miss_conflict") 
			{
				event = EVENT_MISS_CONFLICT;
			}
			else if (a_event == "miss_non_conflict") 
			{
				event = EVENT_MISS_NON_CONFLICT;
			}
			else if (a_event == "missed_acceptance") 
			{
				event = EVENT_MISSED_ACCEPTANCE;
			}
			
			if (event != "")
			{
				m_eventReferenceMap.insert(std::make_pair<std::string, std::string>(event, a_reference));
			}

			return this;
		}
		
		
		ScoreBuilder*
		SetCorrectDecisionLinks(const std::list<std::string>&	a_links, 
								const std::string&				a_correctDecisionLink)
		{
			for (std::list<std::string>::const_iterator it = a_links.begin();
					it != a_links.end(); it++)
			{
				m_correctDecisionLinks[*it] = a_correctDecisionLink;
			}

			return this;
		}

		ScoreBuilder*
		SetIncorrectDecisionLinks(	const std::list<std::string>&	a_links,
									const std::string&				a_incorrectDecisionLink)
		{
			for (std::list<std::string>::const_iterator it = a_links.begin();
					it != a_links.end(); it++)
			{
				m_incorrectDecisionLinks[*it] = a_incorrectDecisionLink;
			}

			return this;
		}

		ScoreBuilder*
		SetGoalSuccessFormula(	const std::string& a_ref1,
								const std::string& a_ref2,
								const std::string& a_comparisonOperator)
		{
			m_goalSuccessFormula.m_ref1 = a_ref1;
			m_goalSuccessFormula.m_ref2 = a_ref2;
			m_goalSuccessFormula.m_comparisonOperator = a_comparisonOperator;

			return this;
		}

		ScoreBuilder*
		SetGoalFailFormula(	const std::string& a_ref1,
							const std::string& a_ref2,
							const std::string& a_comparisonOperator)
		{
			m_goalFailFormula.m_ref1 = a_ref1;
			m_goalFailFormula.m_ref2 = a_ref2;
			m_goalFailFormula.m_comparisonOperator = a_comparisonOperator;

			return this;
		}

		ScoreBuilder*
		SetGoalSuccessScoreMultiplier(int a_multiplier)
		{
			m_goalSuccessScoreMultiplier = a_multiplier;
			
			return this;
		}

		ScoreBuilder*
		SetGoalFailureScore(int a_score)
		{
			m_goalFailureScore = a_score;

			return this;
		}

		Score* build() { return new Score(*this); }

	private:
		int score;
		int m_alreadyActionedScore;
		int m_hitConflictOnTimeScore;
		int m_hitConflictNotOnTimeScore;
		int m_hitAfterConflictScore;
		int m_tooLateConflictScore;
		int m_falseAlarmConflictScore;
		int m_falseAlarmConflictNonTargetScore;

		int m_hitNonConflictScore;
		int m_tooLateNonConflictScore;
		int m_falseAlarmNonConflictScore;
		int m_falseAlarmNonConflictNonTargetScore;

		int m_priorConflictForConflictPairScore;
		int m_priorConflictForNonConflictPairScore;
		int m_priorConflictForNonTargetPairScore;
		int m_priorNonConflictForConflictPairScore;
		int m_priorNonConflictForNonConflictPairScore;
		int m_priorNonConflictForNonTargetPairScore;
		
		int m_missConflictScore;
		int m_missNonConflictScore;
		int missed_acceptance_score;

		std::string m_alreadyActionedAudio;
		std::string m_hitConflictOnTimeAudio;
		std::string m_hitConflictNotOnTimeAudio;
		std::string m_hitAfterConflictAudio;
		std::string m_tooLateConflictAudio;
		std::string m_falseAlarmConflictAudio;
		std::string m_falseAlarmConflictNonTargetAudio;

		std::string m_hitNonConflictAudio;
		std::string m_tooLateNonConflictAudio;
		std::string m_falseAlarmNonConflictAudio;
		std::string m_falseAlarmNonConflictNonTargetAudio;

		std::string m_priorConflictForConflictPairAudio;
		std::string m_priorConflictForNonConflictPairAudio;
		std::string m_priorConflictForNonTargetPairAudio;
		std::string m_priorNonConflictForConflictPairAudio;
		std::string m_priorNonConflictForNonConflictPairAudio;
		std::string m_priorNonConflictForNonTargetPairAudio;

		std::string m_missConflictAudio;
		std::string m_missNonConflictAudio;
		std::string missed_acceptance_audio;

		int m_alreadyActionedAudioDuration;
		int m_hitConflictOnTimeAudioDuration;
		int m_hitConflictNotOnTimeAudioDuration;
		int m_hitAfterConflictAudioDuration;
		int m_tooLateConflictAudioDuration;
		int m_falseAlarmConflictAudioDuration;
		int m_falseAlarmConflictNonTargetAudioDuration;

		int m_hitNonConflictAudioDuration;
		int m_tooLateNonConflictAudioDuration;
		int m_falseAlarmNonConflictAudioDuration;
		int m_falseAlarmNonConflictNonTargetAudioDuration;

		int m_priorConflictForConflictPairAudioDuration;
		int m_priorConflictForNonConflictPairAudioDuration;
		int m_priorConflictForNonTargetPairAudioDuration;
		int m_priorNonConflictForConflictPairAudioDuration;
		int m_priorNonConflictForNonConflictPairAudioDuration;
		int m_priorNonConflictForNonTargetPairAudioDuration;
	
		int m_missConflictAudioDuration;
		int m_missNonConflictAudioDuration;
		int missed_acceptance_audio_duration;

		int m_alreadyActionedDelay;
		int m_hitConflictOnTimeDelay;
		int m_hitConflictNotOnTimeDelay;
		int m_hitAfterConflictDelay;
		int m_tooLateConflictDelay;
		int m_falseAlarmConflictDelay;
		int m_falseAlarmConflictNonTargetDelay;
		int m_hitNonConflictDelay;
		int m_tooLateNonConflictDelay;
		int m_falseAlarmNonConflictDelay;
		int m_falseAlarmNonConflictNonTargetDelay;
		int m_priorConflictForConflictPairDelay;
		int m_priorConflictForNonConflictPairDelay;
		int m_priorConflictForNonTargetPairDelay;
		int m_priorNonConflictForConflictPairDelay;
		int m_priorNonConflictForNonConflictPairDelay;
		int m_priorNonConflictForNonTargetPairDelay;
		int m_missConflictDelay;
		int m_missNonConflictDelay;
		int m_missedAcceptanceDelay;
		
		std::string beep_audio;
		int beep_audio_duration;
		int									m_goalSuccessScoreMultiplier;
		int									m_goalFailureScore;
		GoalAchievementFormula				m_goalSuccessFormula;
		GoalAchievementFormula				m_goalFailFormula;
		std::map<std::string, std::string>	m_eventReferenceMap;
		std::map<std::string, std::string>	m_correctDecisionLinks;
		std::map<std::string, std::string>	m_incorrectDecisionLinks;
	};
};

#endif
